#pragma once
#ifndef xVector_h__
#define xVector_h__

#include "../inc/xType.h"

namespace NLib
{
	template <typename T, TInt N>
	class xVector
	{
	public:
		xVector() {};
		xVector( const xVector& v)
		{
			*this = v;
		}

		xVector(const T d1,...)
		{
			TInt i = 1;
			this->data_[0] = d1;
			va_list va;
			va_start(va, d1);
			while(i < N)
			{
				data_[i] = (T) va_arg(va, const T); 
				i++;
			}
			va_end(va);
		}
		// vector operators
		//xVector& operator += ( const xVector& rhs)
		//{
		//	for(TInt i = N - 1; i >= 0; i --)
		//		data_[i] += rhs[i];
		//}
		//xVector& operator -= ( const xVector& rhs)
		//{
		//	for(TInt i = N - 1; i >= 0; i --)
		//		data_[i] -= rhs[i];
		//	return *this;
		//}
		//xVector& operator *= ( const xVector& rhs)
		//{
		//	for(TInt i = N - 1; i >= 0; i --)
		//		data_[i] *= rhs[i];
		//	return *this;
		//}
		//xVector& operator /= ( const xVector& rhs)
		//{
		//	for(TInt i = N - 1; i >= 0; i --)
		//		data_[i] /= rhs[i];
		//	return *this;
		//}

		////factor operators
		//xVector& operator += ( const T& v )
		//{
		//	for(TInt i = N - 1; i >= 0; i --)
		//		data_[i] += v;
		//	return *this;
		//}
		//xVector& operator -= ( const T& v )
		//{
		//	for(TInt i = N - 1; i >= 0; i --)
		//		data_[i] -= v;
		//	return *this;
		//}
		//xVector& operator *= ( const T& v )
		//{
		//	for(TInt i = N - 1; i >= 0; i --)
		//		data_[i] *= v;
		//	return *this;
		//}
		//xVector& operator /= ( const T& v )
		//{
		//	for(TInt i = N - 1; i >= 0; i --)
		//		data_[i] /= v;
		//}

		////
		//xVector  operator + ( const xVector& rhs )
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//		temp.data_[i] = data_[i] += rhs.data_[i];
		//	return temp;
		//}
		//xVector  operator - ( const xVector& rhs )
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//		temp.data_[i] = data_[i] -= rhs.data_[i];
		//	return temp;
		//}
		//xVector  operator * ( const xVector& rhs )
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//		temp.data_[i] = data_[i] *= rhs.data_[i];
		//	return temp;
		//}
		//xVector  operator / ( const xVector& rhs )
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//		temp.data_[i] = data_[i] /= rhs.data_[i];
		//	return temp;
		//}
		//// binary operators
		//xVector operator + ( const T& v) const
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//		temp[i] = data_[i] + v;
		//	return temp;
		//}
		//xVector operator - ( const T& v) const
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//		temp[i] = data_[i] - v;
		//	return temp;
		//}
		//xVector operator * ( const T& v) const
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//		temp[i] = data_[i] * v;
		//	return temp;
		//}
		//xVector operator / ( const T& v) const
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//		temp[i] = data_[i] / v;
		//	return temp;
		//}
		////friend function
		//friend xVector operator * ( const T v, const xVector& rhs) 
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//	{
		//		temp.data_[i] = v * rhs.data_[i];
		//	}
		//	return temp;
		//}
		//friend xVector operator / ( const T v, const xVector& rhs) 
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//	{
		//		temp.data_[i] = v / rhs.data_[i];
		//	}
		//	return temp;
		//}

		//friend xVector operator + ( const T v, const xVector& rhs) 
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//	{
		//		temp.data_[i] = v + rhs.data_[i];
		//	}
		//	return temp;
		//}

		//friend xVector operator - ( const T v, const xVector& rhs) 
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//	{
		//		temp.data_[i] = v - rhs.data_[i];
		//	}
		//	return temp;
		//}

		//friend xVector operator - ( const xVector& rhs) 
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//	{
		//		temp.data_[i] = -rhs.data_[i];
		//	}
		//	return temp;
		//}

		//compare
		BOOL operator == ( const xVector& rhs) const
		{
			for(TInt i = N - 1; i >= 0; i --)
			{
				if( data_[i] != rhs[i])
					return vFalse;
			}
			return vTrue;
		}

		BOOL operator != ( const xVector& rhs) const
		{
			for(TInt i = N - 1; i >= 0; i --)
			{
				if( data_[0] != rhs[0])
					return vTrue;
			}
			return vFalse;
		}

		TVoid operator =  ( const T& v)
		{
			for(TInt i = N - 1; i >= 0; i --)
				data_[i] = v;
		}
		T&	operator [] (int i)
		{
			xAssert(i < N);
			return data_[i];
		}
		//dist
	public:
		typedef T value_type;
		const static TUint value_size = N;
		

		typedef typename T::value_type sub_value_type;
		typedef typename value_type row_value_type;
		typedef typename xVector<typename T::value_type,value_size> col_value_type;

		const static TUint col_value_size = row_value_type::value_size;
		const static TUint row_value_size = col_value_type::value_size;

		const static TUint atom_type_depth = T::atom_type_depth + 1;
		typedef typename T::atom_value_type atom_value_type;

		template <TInt N>
		struct type_at_depth
		{
			typedef typename xVector::type_at_depth<N-1>::value_type value_type;
		};

		template <>
		struct type_at_depth<0>
		{
			typedef T value_type;
		};
	private:
		T data_[N];

	};


	template <TInt N>
	class xVector<TInt,N>
	{
		typedef TInt T;
	public:
		xVector() {};
		xVector( const xVector& v)
		{
			*this = v;
		}

		xVector(const T d1,...)
		{
			TInt i = 1;
			this->data_[0] = d1;
			va_list va;
			va_start(va, d1);
			while(i < N)
			{
				data_[i] = (T) va_arg(va, const T); 
				i++;
			}
			va_end(va);
		}
		// vector operators
		//xVector& operator += ( const xVector& rhs)
		//{
		//	for(TInt i = N - 1; i >= 0; i --)
		//		data_[i] += rhs[i];
		//}
		//xVector& operator -= ( const xVector& rhs)
		//{
		//	for(TInt i = N - 1; i >= 0; i --)
		//		data_[i] -= rhs[i];
		//	return *this;
		//}
		//xVector& operator *= ( const xVector& rhs)
		//{
		//	for(TInt i = N - 1; i >= 0; i --)
		//		data_[i] *= rhs[i];
		//	return *this;
		//}
		//xVector& operator /= ( const xVector& rhs)
		//{
		//	for(TInt i = N - 1; i >= 0; i --)
		//		data_[i] /= rhs[i];
		//	return *this;
		//}

		////factor operators
		//xVector& operator += ( const T& v )
		//{
		//	for(TInt i = N - 1; i >= 0; i --)
		//		data_[i] += v;
		//	return *this;
		//}
		//xVector& operator -= ( const T& v )
		//{
		//	for(TInt i = N - 1; i >= 0; i --)
		//		data_[i] -= v;
		//	return *this;
		//}
		//xVector& operator *= ( const T& v )
		//{
		//	for(TInt i = N - 1; i >= 0; i --)
		//		data_[i] *= v;
		//	return *this;
		//}
		//xVector& operator /= ( const T& v )
		//{
		//	for(TInt i = N - 1; i >= 0; i --)
		//		data_[i] /= v;
		//}

		////
		//xVector  operator + ( const xVector& rhs )
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//		temp.data_[i] = data_[i] += rhs.data_[i];
		//	return temp;
		//}
		//xVector  operator - ( const xVector& rhs )
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//		temp.data_[i] = data_[i] -= rhs.data_[i];
		//	return temp;
		//}
		//xVector  operator * ( const xVector& rhs )
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//		temp.data_[i] = data_[i] *= rhs.data_[i];
		//	return temp;
		//}
		//xVector  operator / ( const xVector& rhs )
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//		temp.data_[i] = data_[i] /= rhs.data_[i];
		//	return temp;
		//}
		//// binary operators
		//xVector operator + ( const T& v) const
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//		temp[i] = data_[i] + v;
		//	return temp;
		//}
		//xVector operator - ( const T& v) const
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//		temp[i] = data_[i] - v;
		//	return temp;
		//}
		//xVector operator * ( const T& v) const
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//		temp[i] = data_[i] * v;
		//	return temp;
		//}
		//xVector operator / ( const T& v) const
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//		temp[i] = data_[i] / v;
		//	return temp;
		//}
		////friend function
		//friend xVector operator * ( const T v, const xVector& rhs) 
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//	{
		//		temp.data_[i] = v * rhs.data_[i];
		//	}
		//	return temp;
		//}
		//friend xVector operator / ( const T v, const xVector& rhs) 
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//	{
		//		temp.data_[i] = v / rhs.data_[i];
		//	}
		//	return temp;
		//}

		//friend xVector operator + ( const T v, const xVector& rhs) 
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//	{
		//		temp.data_[i] = v + rhs.data_[i];
		//	}
		//	return temp;
		//}

		//friend xVector operator - ( const T v, const xVector& rhs) 
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//	{
		//		temp.data_[i] = v - rhs.data_[i];
		//	}
		//	return temp;
		//}

		//friend xVector operator - ( const xVector& rhs) 
		//{
		//	xVector temp;
		//	for(TInt i = N - 1; i >= 0; i --)
		//	{
		//		temp.data_[i] = -rhs.data_[i];
		//	}
		//	return temp;
		//}

		//compare
		BOOL operator == ( const xVector& rhs) const
		{
			for(TInt i = N - 1; i >= 0; i --)
			{
				if( data_[i] != rhs[i])
					return vFalse;
			}
			return vTrue;
		}

		BOOL operator != ( const xVector& rhs) const
		{
			for(TInt i = N - 1; i >= 0; i --)
			{
				if( data_[0] != rhs[0])
					return vTrue;
			}
			return vFalse;
		}

		TVoid operator =  ( const T& v)
		{
			for(TInt i = N - 1; i >= 0; i --)
				data_[i] = v;
		}
		T&	operator [] (int i)
		{
			xAssert(i < N);
			return data_[i];
		}
		//dist
	public:
		const static TUint value_size = N;
		const static TUint row_value_size = 1;
		const static TUint col_value_size = N;

		const static TUint atom_type_depth = 0;
		typedef T value_type;
		typedef T (col_value_type)[0];
		typedef T atom_value_type;
	private:
		T data_[N];

	};

	//template <typename T,TInt N>
	//T* xVectorDot(T* out,const xVector<T,N>* v1,const xVector<T,N>* v2)
	//{
	//	T v = (*(xVector<T,N>*)v1)[0] * (*(xVector<T,N>*)v2)[0];
	//	for(TInt i = N - 1; i > 0; i --)
	//	{
	//		v += (*(xVector<T,N>*)v1)[i] * (*(xVector<T,N>*)v2)[i];
	//	}
	//	*out = v;
	//	return out;
	//}

	//template <typename T>
	//class xVector<T,1>
	//{
	//public:
	//	xVector() {};
	//	xVector( const xVector& v)
	//	{
	//		this->x = v.x;
	//	}
	//	xVector( const T x)
	//	{
	//		this->x = x;
	//	}

	//	// assignment operators
	//	xVector& operator += ( const xVector& rhs)
	//	{
	//		x += rhs.x;
	//		return *this;
	//	}
	//	xVector& operator -= ( const xVector& rhs)
	//	{
	//		x -= rhs.x;
	//		return *this;
	//	}
	//	xVector& operator *= ( T v )
	//	{
	//		x *= v;
	//		return *this;
	//	}
	//	xVector& operator /= ( T v )
	//	{
	//		x /= v;
	//		return *this;
	//	}

	//	// binary operators
	//	xVector operator + ( const T& rhs) const
	//	{
	//		xVector temp;
	//		temp.x = x + rhs.x;
	//		return temp;
	//	}
	//	xVector operator - ( const T& rhs) const
	//	{
	//		xVector temp;
	//		temp.x = x - rhs.x;
	//		return temp;
	//	}
	//	xVector operator * ( T v ) const
	//	{
	//		xVector temp;
	//		temp.x = x * v;
	//		return temp;
	//	}
	//	xVector operator / ( T v ) const
	//	{
	//		xVector temp;
	//		temp.x = x / v;
	//		return temp;
	//	}

	//	friend xVector operator * ( T v, const xVector& rhs)
	//	{
	//		xVector temp;
	//		temp.x = rhs.x / v;
	//		return temp;
	//	}

	//	BOOL operator == ( const xVector& rhs) const
	//	{
	//		if( x == rhs.x)
	//			return vTrue;
	//		return vFalse;
	//	}

	//	BOOL operator != ( const xVector& rhs) const
	//	{
	//		if( x == rhs.x)
	//			return vFalse;
	//		return vTrue;
	//	}

	//	T&	operator [] (int i)
	//	{
	//		xAssert(i == 0);
	//		return x;
	//	}
	//public:
	//	const static TUint value_size = 1;
	//	typedef T value_type;
	//public:
	//	T    x;
	//};

	//template <typename T>
	//class xVector<T,2>
	//{
	//public:
	//	xVector() {};
	//	xVector( const xVector& v)
	//	{
	//		*this = v;
	//	}

	//	xVector( T x, T y)
	//	{
	//		this->x = x;
	//		this->y = y;
	//	}

	//	// assignment operators
	//	xVector& operator += ( const xVector& rhs)
	//	{
	//		data_[0] += rhs[0];
	//		data_[1] += rhs[1];
	//		return *this;
	//	}
	//	xVector& operator -= ( const xVector& rhs)
	//	{
	//		data_[0] -= rhs[0];
	//		data_[1] -= rhs[1];
	//		return *this;
	//	}
	//	xVector& operator *= ( T v )
	//	{
	//		data_[0] *= v;
	//		data_[1] *= v;
	//		return *this;
	//	}
	//	xVector& operator /= ( T v )
	//	{
	//		data_[0] /= v;
	//		data_[1] /= v;
	//		return *this;
	//	}

	//	// unary operators
	//	xVector operator + () const;
	//	xVector operator - () const;

	//	// binary operators
	//	xVector operator + ( const T& rhs) const
	//	{
	//		xVector temp;
	//		temp[0] = data_[0] + rhs[0];
	//		temp[1] = data_[1] + rhs[1];
	//		return temp;
	//	}
	//	xVector operator - ( const T& rhs) const
	//	{
	//		xVector temp;
	//		temp[0] = data_[0] - rhs[0];
	//		temp[1] = data_[1] - rhs[1];
	//		return temp;
	//	}
	//	xVector operator * ( T v ) const
	//	{
	//		xVector temp;
	//		temp[0] = data_[0] * v;
	//		temp[1] = data_[1] * v;
	//		return temp;
	//	}
	//	xVector operator / ( T v ) const
	//	{
	//		xVector temp;
	//		temp[0] = data_[0] / v;
	//		temp[1] = data_[1] / v;
	//		return temp;
	//	}

	//	friend xVector operator * ( T v, const xVector& rhs)
	//	{
	//		xVector temp;
	//		temp[0] = rhs[0] / v;
	//		temp[1] = rhs[1] / v;
	//		return temp;
	//	}

	//	BOOL operator == ( const xVector& rhs) const
	//	{
	//		if( data_[0] == rhs[0] &&
	//			data_[1] == rhs[1] )
	//			return vTrue;
	//		return vFalse;
	//	}

	//	BOOL operator != ( const xVector& rhs) const
	//	{
	//		if( data_[0] == rhs[0] &&
	//			data_[1] == rhs[1])
	//			return vFalse;
	//		return vTrue;
	//	}

	//	T&	operator [] (int i)
	//	{
	//		switch(i)
	//		{
	//		case 0:
	//			return x;
	//			break;
	//		case 1:
	//			return y;
	//			break;
	//		}
	//		xAssert(vFalse);
	//		return x;
	//	}
	//public:
	//	static TFloat dot(xVector* v1,xVector* v2)
	//	{
	//		float f = v1->x * v2->x;
	//		f += v1->y * v2->y;
	//		return f;
	//	}
	//	static TFloat distance(xVector* v)
	//	{
	//		return sqrtf(dot(v,v));
	//	}
	//public:
	//	const static TUint value_size = 2;
	//	typedef T value_type;
	//public:
	//	T    x,y;
	//};

	//template <typename T>
	//class xVector<T,3>
	//{

	//public:
	//	xVector() {};
	//	xVector( const T v )
	//	{
	//		this->x = v;
	//		this->y = v;
	//		this->z = v;
	//	}

	//	xVector( const xVector& v)
	//	{
	//		*this = v;
	//	}
	//	xVector( T x, T y, T z )
	//	{
	//		this->x = x;
	//		this->y = y;
	//		this->z = z;
	//	}

	//	operator const T* () const;

	//	// assignment operators
	//	xVector& operator += ( const xVector& rhs)
	//	{
	//		x += rhs.x;
	//		y += rhs.y;
	//		z += rhs.z;
	//		return *this;
	//	}
	//	xVector& operator -= ( const xVector& rhs)
	//	{
	//		x -= rhs.x;
	//		y -= rhs.y;
	//		z -= rhs.z;
	//		return *this;
	//	}
	//	xVector& operator *= ( T v )
	//	{
	//		x *= v;
	//		y *= v;
	//		z *= v;
	//		return *this;
	//	}
	//	xVector& operator /= ( T v )
	//	{
	//		x /= v;
	//		y /= v;
	//		z /= v;
	//		return *this;
	//	}


	//	// binary operators
	//	xVector operator + ( const T& rhs) const
	//	{
	//		xVector temp;
	//		temp.x = x + rhs.x;
	//		temp.y = y + rhs.y;
	//		temp.z = z + rhs.z;
	//		return temp;
	//	}
	//	xVector operator - ( const T& rhs) const
	//	{
	//		xVector temp;
	//		temp.x = x - rhs.x;
	//		temp.y = y - rhs.y;
	//		temp.z = z - rhs.z;
	//		return temp;
	//	}
	//	xVector operator * ( T v ) const
	//	{
	//		xVector temp;
	//		temp.x = x * v;
	//		temp.y = y * v;
	//		temp.z = z * v;
	//		return temp;
	//	}
	//	xVector operator / ( T v ) const
	//	{
	//		xVector temp;
	//		temp.x = rhs.x / v;
	//		temp.y = rhs.y / v;
	//		temp.z = rhs.z / v;
	//		return temp;
	//	}

	//	friend xVector operator * ( T v, const xVector& rhs)
	//	{
	//		xVector temp;
	//		temp.x = rhs.x * v;
	//		temp.y = rhs.y * v;
	//		temp.z = rhs.z * v;
	//		return temp;
	//	}

	//	BOOL operator == ( const xVector& rhs) const
	//	{
	//		if( x == rhs.x &&
	//			y == rhs.y &&
	//			z == rhs.z)
	//			return vTrue;
	//		return vFalse;
	//	}

	//	BOOL operator != ( const xVector& rhs) const
	//	{
	//		if( x == rhs.x &&
	//			y == rhs.y &&
	//			z == rhs.z)
	//			return vFalse;
	//		return vTrue;
	//	}
	//	
	//	T&	operator [] (TInt i)
	//	{
	//		switch(i)
	//		{
	//		case 0:
	//			return x;
	//			break;
	//		case 1:
	//			return y;
	//			break;;
	//		case 2:
	//			return z;
	//			break;
	//		}
	//		return x;
	//	}
	//public:
	//	const static TUint value_size = 3;
	//	typedef T value_type;
	//public:
	//	T    x,y,z;
	//};

	//template <typename T>
	//class xVector<T,4>
	//{

	//public:
	//	xVector() {};
	//	xVector( const T v )
	//	{
	//		this->x = v;
	//		this->y = v;
	//		this->z = v;
	//		this->w = v;
	//	}

	//	xVector( const xVector& v)
	//	{
	//		*this = v;
	//	}
	//	xVector( T x, T y, T z,T w)
	//	{
	//		this->x = x;
	//		this->y = y;
	//		this->z = z;
	//		this->w = w;
	//	}

	//	operator const T* () const;

	//	// assignment operators
	//	xVector& operator += ( const xVector& rhs)
	//	{
	//		data_[0] += rhs[0];
	//		data_[1] += rhs[1];
	//		data_[2] += rhs[2];
	//		data_[3] += rhs[3];
	//		return *this;
	//	}
	//	xVector& operator -= ( const xVector& rhs)
	//	{
	//		data_[0] -= rhs[0];
	//		data_[1] -= rhs[1];
	//		data_[2] -= rhs[2];
	//		data_[3] -= rhs[3];
	//		return *this;
	//	}
	//	xVector& operator *= ( T v )
	//	{
	//		data_[0] *= v;
	//		data_[1] *= v;
	//		data_[2] *= v;
	//		data_[3] *= v;
	//		return *this;
	//	}
	//	xVector& operator /= ( T v )
	//	{
	//		data_[0] /= v;
	//		data_[1] /= v;
	//		data_[2] /= v;
	//		data_[3] /= v;
	//		return *this;
	//	}

	//	// unary operators
	//	xVector operator + () const;
	//	xVector operator - () const;

	//	// binary operators
	//	xVector operator + ( const T& rhs) const
	//	{
	//		xVector temp;
	//		temp[0] = data_[0] + rhs[0];
	//		temp[1] = data_[1] + rhs[1];
	//		temp[2] = data_[2] + rhs[2];
	//		temp[3] = data_[3] + rhs[3];
	//		return temp;
	//	}
	//	xVector operator - ( const T& rhs) const
	//	{
	//		xVector temp;
	//		temp[0] = data_[0] - rhs[0];
	//		temp[1] = data_[1] - rhs[1];
	//		temp[2] = data_[2] - rhs[2];
	//		temp[3] = data_[3] - rhs[3];
	//		return temp;
	//	}
	//	xVector operator * ( T v ) const
	//	{
	//		xVector temp;
	//		temp[0] = data_[0] * v;
	//		temp[1] = data_[1] * v;
	//		temp[2] = data_[2] * v;
	//		temp[3] = data_[3] * v;
	//		return temp;
	//	}
	//	xVector operator / ( T v ) const
	//	{
	//		xVector temp;
	//		temp[0] = data_[0] / v;
	//		temp[1] = data_[1] / v;
	//		temp[2] = data_[2] / v;
	//		temp[3] = data_[3] / v;
	//		return temp;
	//	}

	//	friend xVector operator * ( T v, const xVector& rhs)
	//	{
	//		xVector temp;
	//		temp[0] = rhs[0] / v;
	//		temp[1] = rhs[1] / v;
	//		temp[2] = rhs[2] / v;
	//		temp[3] = rhs[3] / v;
	//		return temp;
	//	}

	//	BOOL operator == ( const xVector& rhs) const
	//	{
	//		if( data_[0] == rhs[0] &&
	//			data_[1] == rhs[1] &&
	//			data_[2] == rhs[2] &&
	//			data_[3] == rhs[3])
	//			return vTrue;
	//		return vFalse;
	//	}

	//	BOOL operator != ( const xVector& rhs) const
	//	{
	//		if( data_[0] == rhs[0] &&
	//			data_[1] == rhs[1] &&
	//			data_[2] == rhs[2] &&
	//			data_[3] == rhs[3])
	//			return vFalse;
	//		return vTrue;
	//	}

	//	T&	operator [] (int i)
	//	{
	//		switch(i)
	//		{
	//		case 0:
	//			return x;
	//			break;
	//		case 1:
	//			return y;
	//			break;;
	//		case 2:
	//			return z;
	//			break;
	//		case 3:
	//			return w;
	//			break;
	//		}
	//		xAssert(vFalse);
	//		return x;
	//	}
	//public:
	//	const static TUint value_size = 4;
	//	typedef T value_type;
	//public:
	//	T    x,y,z,w;
	//};

	//typedef xVector<TInt,1>		TInt1;
	//typedef xVector<TInt,2>		TInt2;
	//typedef xVector<TInt,3>		TInt3;
	//typedef xVector<TInt,4>		TInt4;
	//typedef xVector<TInt4,4>	TInt4x4;
	//typedef xVector<TInt4x4,4>	TInt4x4x4;
	//
#define VECTOR_DEF1(type,size)			typedef xVector<type,size>									TInt##size
#define VECTOR_DEF2(type,row,col)		typedef xVector<xVector<type,col>,row>						TInt##row##x##col
#define VECTOR_DEF3(type,row,col,size)	typedef xVector<xVector<xVector<type,col>,size>,row>		TInt##row##x##col##x##size

	VECTOR_DEF1(TInt,1);
	VECTOR_DEF1(TInt,2);
	VECTOR_DEF1(TInt,3);
	VECTOR_DEF1(TInt,4);
	VECTOR_DEF2(TInt,4,4);
}

#include <iostream>

namespace NLib
{
	namespace NInternal
	{
		struct vector_math_helper
		{
			// A = c + B
			template <typename TC,typename T,typename TSUB>
			static T& coff_add(T& out,const TC coff,const T& in,const TSUB& sub)
			{
				for(TInt i = 0; i < T::value_size; i ++)
				{
					vector_math_helper::coff_add(&((typename T::value_type&)(out)[i]),coff,in[i],in[i][0]);
				}
				return out;
			}
			template <typename TC,typename T>
			static T& coff_add(T& out,TC coff,const T& in,const TInt& sub)
			{
				for(TInt i = 0; i < T::value_size; i ++)
				{
					out[i] = coff + ((T&)in)[i];
				}
				return out;
			}
			// A = B + C
			template <typename T,typename TSUB>
			static T& ele_add(T& out,const T& t1,const T& t2,const TSUB& sub)
			{
				for(TInt i = 0; i < T::value_size; i ++)
				{
					vector_math_helper::ele_add((typename T::value_type&)(out[i]),(typename T::value_type&)(((T&)t1)[i]),(typename T::value_type&)(((T&)t2)[i]),((T::value_type&)((T&)t1)[i])[0]);
				}
				return out;
			}
			template <typename T>
			static T& ele_add(T& out,const T& t1,const T& t2,const TInt& sub)
			{
				for(TInt i = 0; i < T::value_size; i ++)
				{
					out[i] = ele_add(out[i],((T&)t1)[i],((T&)t2)[i]);
				}
				return out;
			}
			static TInt& ele_add(TInt& out,const TInt& t1,const TInt& t2)
			{
				out = t1 + t2;
				return out;
			}
			// A = c - B
			template <typename TC,typename T,typename TSUB>
			static T& coff_sub(T& out,const TC coff,const T& in,const TSUB& sub)
			{
				for(TInt i = 0; i < T::value_size; i ++)
				{
					vector_math_helper::coff_sub(&((typename T::value_type&)(out)[i]),coff,in[i],in[i][0]);
				}
				return out;
			}
			template <typename TC,typename T>
			static T& coff_sub(T& out,TC coff,const T& in,const TInt& sub)
			{
				for(TInt i = 0; i < T::value_size; i ++)
				{
					out[i] = coff - ((T&)in)[i];
				}
				return out;
			}
			//A = B - C
			template <typename T,typename TSUB>
			static T& ele_sub(T& out,const T& t1,const T& t2,const TSUB& sub)
			{
				for(TInt i = 0; i < T::value_size; i ++)
				{
					vector_math_helper::ele_sub((typename T::value_type&)(out[i]),(typename T::value_type&)(((T&)t1)[i]),(typename T::value_type&)(((T&)t2)[i]),((T::value_type&)((T&)t1)[i])[0]);
				}
				return out;
			}
			template <typename T>
			static T& ele_sub(T& out,const T& t1,const T& t2,const TInt& sub)
			{
				for(TInt i = 0; i < T::value_size; i ++)
				{
					out[i] = ((T&)t1)[i] - ((T&)t2)[i];
				}
				return out;
			}
			// A = c * B
			template <typename TC,typename T,typename TSUB>
			static T& coff_mul(T& out,const TC coff,const T& in,const TSUB& sub)
			{
				for(TInt i = 0; i < T::value_size; i ++)
				{
					vector_math_helper::coff_mul(((out)[i]),coff,(((T&)in)[i]),((T::value_type&)((T&)in)[i])[0]);
				}
				return out;
			}
			template <typename TC,typename T>
			static T& coff_mul(T& out,TC coff,const T& in,const TInt& sub)
			{
				for(TInt i = 0; i < T::value_size; i ++)
				{
					out[i] = coff * ((T&)in)[i];
				}
				return out;
			}
			// A = c / B
			template <typename TC,typename T,typename TSUB>
			static T& coff_div(T& out,const TC coff,const T& in,const TSUB& sub)
			{
				for(TInt i = 0; i < T::value_size; i ++)
				{
					vector_math_helper::coff_div(&((typename T::value_type&)(out)[i]),coff,in[i],in[i][0]);
				}
				return out;
			}
			template <typename TC,typename T>
			static T& coff_div(T& out,TC coff,const T& in,const TInt& sub)
			{
				for(TInt i = 0; i < T::value_size; i ++)
				{
					if(((T&)in)[i] == 0)
						out[i] = vMaxInt;
					else
						out[i] = coff / ((T&)in)[i];
				}
				return out;
			}
			// A = B * C
			template <typename T,typename TSUB>
			static T& ele_mul(T& out,const T& t1,const T& t2,const TSUB& sub)
			{
				for(TInt i = 0; i < T::value_size; i ++)
				{
					vector_math_helper::ele_mul((typename T::value_type&)(out[i]),(typename T::value_type&)(((T&)t1)[i]),(typename T::value_type&)(((T&)t2)[i]),((T::value_type&)((T&)t1)[i])[0]);
				}
				return out;
			}
			template <typename T>
			static T& ele_mul(T& out,const T& t1,const T& t2,const TInt& sub)
			{
				for(TInt i = 0; i < T::value_size; i ++)
				{
					out[i] = ((T&)t1)[i] * ((T&)t2)[i];
				}
				return out;
			}
			// A = B dot C
			template <typename T,typename TSUB>
			static T& dot_mul(T& out,const T& t1,const T& t2,const TSUB& sub)
			{
				for(TInt i = 0; i < T::value_size; i ++)
				{
					vector_math_helper::ele_mul(&((typename T::value_type&)(out)[i]),t1,t2,t1[i][0]);
				}
				return out;
			}
			template <typename T>
			static TInt& dot_mul(TInt& out,const T& t1,const T& t2,const TInt& sub)
			{
				out = 0;
				for(TInt i = 0; i < T::value_size; i ++)
				{
					out  += ((T&)t1)[i] * ((T&)t2)[i];
				}
				return out;
			}
			template <typename T>
			static T& dot_mul(T& out,const T& t1,const T& t2)
			{
				for(TInt i = 0; i < T::value_size; i ++)
				{
					vector_math_helper::ele_mul(&((typename T::value_type&)(out)[i]),t1,t2,t1[i][0]);
				}
				return out;
			}
			static TInt& dot_mul(TInt& out,const TInt& t1,const TInt& t2)
			{
				out = t1 * t2;
				return out;
			}
			template <typename T>
			static T& dot_mul_add(T& out,const T& t1,const T& t2)
			{
				typename T::value_type& tmp;
				for(TInt i = 0; i < T::value_size; i ++)
				{
					vector_math_helper::ele_add(((typename T::value_type&)(out)[i]),tmp,vector_math_helper::ele_mul_mul(tmp,t1,t2,t1[i][0]));
				}
				return out;
			}
			static TInt& dot_mul_add(TInt& out,const TInt& t1,const TInt& t2)
			{
				out += t1 * t2;
				return out;
			}
		};

		
		//TVoid print_helper(const TInt& t)
		//{
		//	std::cout<<"\t";
		//	std::cout<<t;
		//	std::cout<<std::endl;
		//}
		//template <typename T>
		//TVoid print_helper(const T& t)
		//{
		//	for(TInt i = 0; i < T::value_size; i ++)
		//	{
		//		std::cout<<"\t";
		//		print_sub_helper(((T&)t)[i]);
		//	}
		//	std::cout<<std::endl;
		//}
		//template <typename T>
		/*TVoid print_sub_helper(const T& t)
		{
			for(TInt i = 0; i < T::value_size; i ++)
			{
				print_sub_helper(((T&)t)[i]);
				std::cout<<"\t";
			}
			std::cout<<std::endl;
		}
		template <>
		TVoid print_sub_helper(const TInt& t)
		{
			std::cout<<t<<"\t";
		};*/
	}
	//out = v1 + v2
	template <typename T>
	T& vector_ele_add(T& out, T& v1,T& v2)
	{
		return NInternal::vector_math_helper::ele_add(out,v1,v2,v2[0]);
	}
	//out = v1 - v2
	template <typename T>
	T& vector_ele_sub(T& out, T& v1,T& v2)
	{
		return NInternal::vector_math_helper::ele_sub(out,v1,v2,v2[0]);
	}
	//out = c + v
	template <typename TC,typename T>
	T& vector_coeff_add(T& out, const TC coff,T& v)
	{
		return NInternal::vector_math_helper::coff_add(out,coff,v,v[0]);
	}
	//out = c - v
	template <typename TC,typename T>
	T& vector_coeff_sub(T& out, const TC coff,T& t)
	{
		return NInternal::vector_math_helper::coff_sub(out,coff,t,t[0]);
	}

	template <typename TC,typename T>
	T& vector_coeff_mul(T& out, const TC coff,T& v)
	{
		return NInternal::vector_math_helper::coff_mul(out,coff,v,(v[0]));
	}
	//out = coff * v
	template <typename TC,typename T>
	T& vector_coeff_div(T& out, const TC coff,T& v)
	{
		return NInternal::vector_math_helper::coff_div(out,coff,v,v[0]);
	}

	// out = v1 * v2
	template <typename T>
	T& vector_ele_mul(T& out, T& v1,T& v2)
	{
		return NInternal::vector_math_helper::ele_mul(out,v1,v2,v1[0]);
	}
	//out = t1 dot t2
	template <typename T>
	typename T::value_type& vector_dot_mul(T& out, T& t1,typename T::value_type& t2)
	{
		return NInternal::vector_math_helper::dot_mul(out,t1,t2,t1[0]);
	}
	// v1 dot v2
	template <typename T>
	typename T::atom_value_type& vector_dot_mul(typename T::atom_value_type& out,T& t1,T& t2)
	{
		return NInternal::vector_math_helper::dot_mul(out,t1,t2,t1[0]);
	}
	//out = mtx * v
	template <typename T>
	typename T::col_value_type& vector_mtx_mul_transpose(typename T::col_value_type& out,T& mtx,typename T::value_type& v)
	{
		for(TInt i = T::value_size - 1; i >= 0 ; i --)
		{
			vector_dot_mul((typename T::col_value_type::value_type&)(out[i]),mtx[i],v);
		}
		return out;
	}
	//out = v * mtx
	template <typename T>
	typename T::value_type& vector_mtx_mul(typename T::value_type& out,typename T::col_value_type& v,T& mtx)
	{
		for(TInt c = T::col_value_size - 1; c >= 0 ; c --)
		{
			NInternal::vector_math_helper::dot_mul(out[c],v[0],mtx[0][c]);
			for(TInt r = T::value_size - 1; r > 0 ; r --)
			{
				NInternal::vector_math_helper::dot_mul_add((typename T::value_type::value_type&)(out[c]),v[r],mtx[r][c]);
			}
		}
		return out;
	}
	//
	//out = mtx * mtx
	template <typename T>
	typename T& vector_mtx_mul(T& out,T& m1,T& m2)
	{
		if(&out != &m1 &&
			&out != &m2)
		{
			for(TInt r = T::row_value_size - 1; r >= 0 ; r --)
			{
				{
					vector_mtx_mul(out[r],m1[r],m2);
				}
			}
			return out;
		}
		else
		{
			T tmp;
			for(TInt r = T::row_value_size - 1; r >= 0 ; r --)
			{
				{
					vector_mtx_mul(tmp[r],m1[r],m2);
				}
			}
			out = tmp;
			return out;
		}
		return out;
	}
	template <typename T1,typename T2,typename T3>
	typename T1& vector_mtx_mul(T1& out,T2& m1,T3& m2)
	{
		/*if(&out != &m1 &&
			&out != &m2)*/
		{
			for(TInt r = T2::row_value_size - 1; r >= 0 ; r --)
			{
				{
					vector_mtx_mul(out[r],m1[r],m2);
				}
			}
			return out;
		}
		/*else
		{
			T1 tmp;
			for(TInt r = T3::row_value_size - 1; r >= 0 ; r --)
			{
				{
					vector_mtx_mul(tmp[r],m1[r],m2);
				}
			}
			out = tmp;
			return out;
		}*/
		return out;
	}

	/*template <typename T>
	TVoid vector_print(char* arg,const T& t)
	{
		cout<<arg<<endl;
		NInternal::print_helper(t);
		cout<<endl;
	}*/
}

#endif // xVector_h__